package com.timber.util;

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import com.borland.jbcl.layout.*;
import pv.jfcx.*;


// Comparator used to sort master list of column names for the master column list
class ColumnNameComparator implements Comparator
{
  public int compare( Object o1, Object o2 )
  {
    SLColumnDefinition cd1 = ( SLColumnDefinition )o1;
    SLColumnDefinition cd2 = ( SLColumnDefinition )o2;

    String str1 = cd1.getColEditString();
    String str2 = cd2.getColEditString();

    return str1.compareTo( str2 );
  }

  public boolean equals( Object o )
  {
    return super.equals( o );
  }
}

// Display an ascending/descending icon and a column name for each object in the sort list.
class SortListRenderer extends DefaultListCellRenderer
{
  final static ImageIcon ascendingIcon  = ImageMgr.getIcon( ImageMgr.ASCENDING_ICON );
  final static ImageIcon descendingIcon = ImageMgr.getIcon( ImageMgr.DESCENDING_ICON );


  // This is the only method defined by ListCellRenderer.
  // We just reconfigure the JLabel each time we're called.

  public Component getListCellRendererComponent( JList   list,
						 Object  value,
						 int     index,
						 boolean isSelected,
						 boolean cellHasFocus )
  {
    setComponentOrientation( list.getComponentOrientation() );

    if( isSelected)
    {
      setBackground( list.getSelectionBackground() );
      setForeground( list.getSelectionForeground() );
    }
    else
    {
      setBackground( list.getBackground() );
      setForeground( list.getForeground() );
    }

    String s = value.toString();
    setText( s );

    SLColumnDefinition cd = ( SLColumnDefinition )value;
    setIcon( ( cd.sortAscending ? ascendingIcon : descendingIcon ) );

    setEnabled( list.isEnabled() );
    setFont( list.getFont() );
    setBorder( ( cellHasFocus ) ?
	       UIManager.getBorder( "List.focusCellHighlightBorder" ) :
	       noFocusBorder );

    return this;
  }
}


public class SLColumnEditorDialog extends JDialog
{
  protected JPanel		mainPanel = new JPanel();
  protected JPanel		centerPanel = new JPanel();
  protected JPanel		listsPanel = new JPanel();
  protected JPanel		lockedColsPanel = new JPanel();
  protected JPanel		btnPanel1 = new JPanel();
  protected JPanel		btnPanel2 = new JPanel();
  protected JPanel		bottomPanel = new JPanel();
  protected JPanel		mainBtnPanel = new JPanel();
  protected BorderLayout	borderLayout1 = new BorderLayout();
  protected BorderLayout	borderLayout2 = new BorderLayout();
  protected BorderLayout	borderLayout3 = new BorderLayout();
  protected BoxLayout2		boxLayout21 = new BoxLayout2();
  protected VerticalFlowLayout	verticalFlowLayout1 = new VerticalFlowLayout();
  protected VerticalFlowLayout	verticalFlowLayout2 = new VerticalFlowLayout();
  protected FlowLayout		flowLayout1 = new FlowLayout();
  protected FlowLayout		flowLayout2 = new FlowLayout();
  protected Border		border1;
  protected Border		border2;
  protected Border		border3;
  protected TitledBorder	titledBorder1;
  protected TitledBorder	titledBorder2;
  protected TitledBorder	titledBorder3;
  protected JScrollPane		allColumnsSP = new JScrollPane();
  protected JScrollPane		userColsSP = new JScrollPane();
  protected JScrollPane		sortColsSP = new JScrollPane();
  protected JList		allColumnsList = new JList();
  protected JList		userColsList = new JList();
  protected JList		sortColsList = new JList();
  protected JButton		addToUserCols = new JButton();
  protected JButton		addAllToUserCols = new JButton();
  protected JButton		removeFromUserCols = new JButton();
  protected JButton		moveUserColUp = new JButton();
  protected JButton		moveUserColDown = new JButton();
  protected JButton		clearAllUserCols = new JButton();
  protected JButton		addToSortCols = new JButton();
  protected JButton		removeFromSortCols = new JButton();
  protected JButton		moveSortColUp = new JButton();
  protected JButton		moveSortColDown = new JButton();
  protected JButton		clearAllSortCols = new JButton();
  protected JButton		okBtn = new JButton();
  protected JButton		cancelBtn = new JButton();
  protected JSeparator		jSeparator1 = new JSeparator();
  protected Component		component1;
  protected Component		component2;
  protected Vector		allColumns;
  protected Vector		userColumns;
  protected Vector		sortColumns;
  protected SLTableModel	tm;
  protected JFrame		parent;
  protected JLabel		lockedColsLabel = new JLabel( "Locked Columns" );
  protected JPVSpinPlus		lockedColsSpin = new JPVSpinPlus( JPVSpin.VERTICAL_RIGHT,
								  JPVSpinPlus.NUMERIC,
								  true );
  protected JPVNumeric		lockedColsTF = ( JPVNumeric )lockedColsSpin.getObject();
  protected int			numLockedCols;
  protected ColumnNameComparator	columnNameComparator = new ColumnNameComparator();


  public SLColumnEditorDialog( JFrame parent, SLTableModel tm, int numLockedCols )
  {
    super( parent, true );
    this.parent = parent;
    this.tm = tm;
    this.numLockedCols = numLockedCols;

    try
    {
      jbInit();
      pack();
    }
    catch( Exception ex )
    {
      ex.printStackTrace();
    }
  }

  void jbInit() throws Exception
  {
    this.setTitle( "Column Configurator" );

    border1 = BorderFactory.createEtchedBorder( Color.white, new Color( 178, 178, 178 ) );
    titledBorder1 = new TitledBorder( border1, "All Columns" );

    border2 = BorderFactory.createEtchedBorder( Color.white, new Color( 178, 178, 178 ) );
    titledBorder2 = new TitledBorder( border1, "User Columns" );

    border3 = BorderFactory.createEtchedBorder( Color.white, new Color( 178, 178, 178 ) );
    titledBorder3 = new TitledBorder( border3, "Sort Columns" );

    component1 = Box.createHorizontalStrut( 20 );
    component2 = Box.createVerticalStrut( 5 );

    mainPanel.setLayout( borderLayout1 );
    centerPanel.setLayout( borderLayout3 );
    listsPanel.setLayout( boxLayout21 );
    lockedColsPanel.setLayout( flowLayout2 );
    bottomPanel.setLayout( borderLayout2 );
    mainBtnPanel.setLayout( flowLayout1 );

    flowLayout1.setHgap( 10 );
    flowLayout1.setVgap( 10 );
    borderLayout2.setVgap( 5 );
    borderLayout1.setHgap( 5 );
    borderLayout1.setVgap( 5 );

    verticalFlowLayout1.setAlignment( VerticalFlowLayout.MIDDLE );
    verticalFlowLayout2.setAlignment( VerticalFlowLayout.MIDDLE );

    btnPanel1.setLayout( verticalFlowLayout1 );
    btnPanel2.setLayout( verticalFlowLayout2 );

    allColumnsList.setFixedCellWidth( 200 );
    allColumnsList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );

    userColsList.setFixedCellWidth (200 );
    userColsList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );

    sortColsList.setFixedCellWidth( 200 );
    sortColsList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
    sortColsList.setCellRenderer( new SortListRenderer() );
    sortColsList.setToolTipText( "Double click to toggle sort direction" );
    sortColsList.addMouseListener( new MouseAdapter()
      {
	public void mouseClicked( MouseEvent me )
	{
	  if( me.getClickCount() == 2 && SwingUtilities.isLeftMouseButton( me ) )
	  {
	    int row = sortColsList.locationToIndex( me.getPoint() );
	    if( row != -1 )
	    {
	      toggleSortDirection( row );
	    }
	  }
	}
      } );

    allColumnsSP.setBorder( titledBorder1 );
    userColsSP.setBorder( titledBorder2 );
    sortColsSP.setBorder( titledBorder3 );

    addToUserCols.setText( "Add >>" );
    addToUserCols.addActionListener( new java.awt.event.ActionListener()
    {
      public void actionPerformed( ActionEvent e )
      {
        addToUserCols_actionPerformed();
      }
    });

    addAllToUserCols.setText( "Add All >>" );
    addAllToUserCols.addActionListener( new java.awt.event.ActionListener()
    {
      public void actionPerformed( ActionEvent e )
      {
        addAllToUserCols_actionPerformed();
      }
    });

    removeFromUserCols.setText( "Remove" );
    removeFromUserCols.addActionListener( new java.awt.event.ActionListener()
    {
      public void actionPerformed( ActionEvent e )
      {
        removeFromUserCols_actionPerformed();
      }
    });

    moveUserColUp.setText( "Move Up" );
    moveUserColUp.addActionListener( new java.awt.event.ActionListener()
    {
      public void actionPerformed( ActionEvent e )
      {
        moveUserColUp_actionPerformed();
      }
    });

    moveUserColDown.setText( "Move Down" );
    moveUserColDown.addActionListener( new java.awt.event.ActionListener()
    {
      public void actionPerformed( ActionEvent e )
      {
        moveUserColDown_actionPerformed();
      }
    });

    clearAllUserCols.setText( "Clear All" );
    clearAllUserCols.addActionListener( new java.awt.event.ActionListener()
    {
      public void actionPerformed( ActionEvent e )
      {
        clearAllUserCols_actionPerformed();
      }
    });

    addToSortCols.setText( "Add >>" );
    addToSortCols.addActionListener( new java.awt.event.ActionListener()
    {
      public void actionPerformed( ActionEvent e )
      {
        addToSortCols_actionPerformed();
      }
    });

    removeFromSortCols.setText( "Remove" );
    removeFromSortCols.addActionListener( new java.awt.event.ActionListener()
    {
      public void actionPerformed( ActionEvent e )
      {
        removeFromSortCols_actionPerformed();
      }
    });

    moveSortColUp.setText( "Move Up" );
    moveSortColUp.addActionListener( new java.awt.event.ActionListener()
    {
      public void actionPerformed( ActionEvent e )
      {
        moveSortColUp_actionPerformed();
      }
    });

    moveSortColDown.setText( "Move Down" );
    moveSortColDown.addActionListener( new java.awt.event.ActionListener()
    {
      public void actionPerformed( ActionEvent e )
      {
        moveSortColDown_actionPerformed();
      }
    });

    clearAllSortCols.setText( "Clear All" );
    clearAllSortCols.addActionListener( new java.awt.event.ActionListener()
    {
      public void actionPerformed( ActionEvent e )
      {
        clearAllSortCols_actionPerformed();
      }
    });

    okBtn.setText( "Ok" );
    okBtn.addActionListener( new java.awt.event.ActionListener()
    {
      public void actionPerformed( ActionEvent e )
      {
        okBtn_actionPerformed();
      }
    });

    cancelBtn.setText( "Cancel" );
    cancelBtn.addActionListener( new java.awt.event.ActionListener()
    {
      public void actionPerformed( ActionEvent e )
      {
        cancelBtn_actionPerformed();
      }
    });

    lockedColsTF.setToolTipText( "Number of columns to lock on left" );
    lockedColsTF.setColumns( 3 );
    lockedColsTF.setMinValue( 0 );
    lockedColsTF.setLong( numLockedCols );

    getContentPane().add( mainPanel );

    mainPanel.add( centerPanel, BorderLayout.CENTER );
    mainPanel.add( bottomPanel, BorderLayout.SOUTH );

    centerPanel.add( listsPanel, BorderLayout.CENTER );
//     centerPanel.add( lockedColsPanel, BorderLayout.SOUTH );

    listsPanel.add( allColumnsSP, null );
    listsPanel.add( btnPanel1, null );
    listsPanel.add( userColsSP, null );
    listsPanel.add( btnPanel2, null );
    listsPanel.add( sortColsSP, null );

    lockedColsPanel.add( lockedColsLabel, null );
    lockedColsPanel.add( lockedColsSpin, null );

    bottomPanel.add( component2, BorderLayout.NORTH );
    bottomPanel.add( jSeparator1, BorderLayout.CENTER );
    bottomPanel.add( mainBtnPanel, BorderLayout.SOUTH );

    mainBtnPanel.add( okBtn, null );
    mainBtnPanel.add( component1, null );
    mainBtnPanel.add( cancelBtn, null );

    allColumnsSP.getViewport().add( allColumnsList, null );
    userColsSP.getViewport().add( userColsList, null );
    sortColsSP.getViewport().add( sortColsList, null );

    btnPanel1.add( addToUserCols, null );
    btnPanel1.add( addAllToUserCols, null );
    btnPanel1.add( removeFromUserCols, null );
    btnPanel1.add( moveUserColUp, null );
    btnPanel1.add( moveUserColDown, null );
    btnPanel1.add( clearAllUserCols, null );

    btnPanel2.add( addToSortCols, null );
    btnPanel2.add( removeFromSortCols, null );
    btnPanel2.add( moveSortColUp, null );
    btnPanel2.add( moveSortColDown, null );
    btnPanel2.add( clearAllSortCols, null );

    populateLists();
  }

  protected void populateLists()
  {
    //  Get the master list of visible columns
    Vector v = ( Vector )tm.getMasterColumnList().clone();
    allColumns = new Vector( v.size() );
    for( int i = 0; i < v.size(); i++ )
    {
      SLColumnDefinition cd = ( SLColumnDefinition )v.elementAt( i );
      if( cd.isVisible() )
	allColumns.add( cd );
    }
    
    //  Sort the master column list
    Collections.sort( allColumns, columnNameComparator );

    //  Get the user's list of visible columns
    v = ( Vector )tm.getColumnList().clone();
    userColumns = new Vector( v.size() );
    for( int i = 0; i < v.size(); i++ )
    {
      SLColumnDefinition cd = ( SLColumnDefinition )v.elementAt( i );
      if( cd.isVisible() )
	userColumns.add( cd );
    }

    getSortCols();

    allColumnsList.setListData( allColumns );
    userColsList.setListData( userColumns );
    sortColsList.setListData( sortColumns );

    if( allColumns.size() > 0 )
      allColumnsList.setSelectedIndex( 0 );

    if( userColumns.size() > 0 )
      userColsList.setSelectedIndex( 0 );

    if( sortColumns.size() > 0 )
      sortColsList.setSelectedIndex( 0 );

    lockedColsTF.setMaxValue( userColumns.size() );
  }

  public int showDialog()
  {
    Dimension frmSize;
    Point loc;
    Dimension dlgSize = getPreferredSize();
    if( parent != null )
    {
      frmSize = parent.getSize();
      loc = parent.getLocation();
    }
    else
    {
      frmSize = Toolkit.getDefaultToolkit().getScreenSize();
      loc = new Point();
    }
    setLocation( ( frmSize.width - dlgSize.width ) / 2 + loc.x,
		 ( frmSize.height - dlgSize.height ) / 2 + loc.y );
    show();

    return numLockedCols;
  }

  protected void processWindowEvent( WindowEvent e )
  {
    if( e.getID() == WindowEvent.WINDOW_CLOSING )
    {
      cancelBtn_actionPerformed();
    }
    super.processWindowEvent( e );
  }

  protected void getSortCols()
  {
    TreeMap sortCols = new TreeMap();;

    for( Enumeration e = userColumns.elements(); e.hasMoreElements(); )
    {
      SLColumnDefinition cd = ( SLColumnDefinition )e.nextElement();
      int sortPos = cd.getSortPos();
      if( sortPos != -1 )
      {
	sortCols.put( new Integer( sortPos ), cd );
      }
    }

    if( sortCols.size() > 0 )
      sortColumns = new Vector( sortCols.values() );
    else
      sortColumns = new Vector();
  }

  protected void addToUserCols_actionPerformed()
  {
    int idx = allColumnsList.getSelectedIndex();
    if( idx == -1 )
      return;

    SLColumnDefinition cd = ( SLColumnDefinition )allColumns.elementAt( idx );
    if( userColumns.contains( cd ) == false )
    {
      userColumns.add( cd );

      userColsList.setListData( userColumns );
      userColsList.setSelectedIndex( userColumns.size() - 1 );
    }

    lockedColsTF.setMaxValue( userColumns.size() );
    if( lockedColsTF.getLong() > userColumns.size() )
      lockedColsTF.setLong( userColumns.size() );
  }

  protected void addAllToUserCols_actionPerformed()
  {
    userColumns = ( Vector )allColumns.clone();
    userColsList.setListData( userColumns );
    userColsList.setSelectedIndex( 0 );
    lockedColsTF.setMaxValue( userColumns.size() );
    if( lockedColsTF.getLong() > userColumns.size() )
      lockedColsTF.setLong( userColumns.size() );
  }

  protected void removeFromUserCols_actionPerformed()
  {
    int idx = userColsList.getSelectedIndex();
    if( idx == -1 )
      return;

    Object o = userColumns.remove( idx );
    userColsList.setListData( userColumns );
    userColsList.setSelectedIndex( idx );

    if( sortColumns.remove( o ) == true )
    {
      sortColsList.setListData( sortColumns );
    }

    lockedColsTF.setMaxValue( userColumns.size() );
    if( lockedColsTF.getLong() > userColumns.size() )
      lockedColsTF.setLong( userColumns.size() );
  }

  protected void moveUserColUp_actionPerformed()
  {
    int idx = userColsList.getSelectedIndex();
    if( idx < 1 )
      return;

    Object o = userColumns.remove( idx );
    userColumns.insertElementAt( o, idx - 1 );

    userColsList.setListData( userColumns );
    userColsList.setSelectedIndex( idx - 1 );
  }

  protected void moveUserColDown_actionPerformed()
  {
    int idx = userColsList.getSelectedIndex();
    if( idx == -1 || idx == ( userColumns.size() - 1 ) )
      return;

    Object o = userColumns.remove( idx );
    userColumns.insertElementAt( o, idx + 1 );

    userColsList.setListData( userColumns );
    userColsList.setSelectedIndex( idx + 1 );
  }

  protected void clearAllUserCols_actionPerformed()
  {
    userColumns.clear();
    userColsList.setListData( userColumns );
    clearAllSortCols_actionPerformed();
    lockedColsTF.setMaxValue( userColumns.size() );
    if( lockedColsTF.getLong() > userColumns.size() )
      lockedColsTF.setLong( userColumns.size() );
  }

  protected void addToSortCols_actionPerformed()
  {
    if( sortColumns.size() > 2 )
    {
      JOptionPane.showMessageDialog( null,
				     "Maximum of 3 sort columns allowed",
				     "Maximum Exceeded",
				     JOptionPane.ERROR_MESSAGE );
      return;
    }

    int idx = userColsList.getSelectedIndex();
    if( idx == -1 )
      return;

    SLColumnDefinition cd = ( SLColumnDefinition )userColumns.elementAt( idx );
    if( sortColumns.contains( cd ) == false )
    {
      sortColumns.add( cd );

      sortColsList.setListData( sortColumns );
      sortColsList.setSelectedIndex( sortColumns.size() - 1 );
    }
  }

  protected void removeFromSortCols_actionPerformed()
  {
    int idx = sortColsList.getSelectedIndex();
    if( idx == -1 )
      return;

    sortColumns.removeElementAt( idx );
    sortColsList.setListData( sortColumns );
    sortColsList.setSelectedIndex( idx );
  }

  protected void moveSortColUp_actionPerformed()
  {
    int idx = sortColsList.getSelectedIndex();
    if( idx < 1 )
      return;

    Object o = sortColumns.remove( idx );
    sortColumns.insertElementAt( o, idx - 1 );

    sortColsList.setListData( sortColumns );
    sortColsList.setSelectedIndex( idx - 1 );
  }

  protected void moveSortColDown_actionPerformed()
  {
    int idx = sortColsList.getSelectedIndex();
    if( idx == -1 || idx == ( sortColumns.size() - 1 ) )
      return;

    Object o = sortColumns.remove( idx );
    sortColumns.insertElementAt( o, idx + 1 );

    sortColsList.setListData( sortColumns );
    sortColsList.setSelectedIndex( idx + 1 );
  }

  protected void clearAllSortCols_actionPerformed()
  {
    sortColumns = new Vector();
    sortColsList.setListData( sortColumns );
  }

  protected void okBtn_actionPerformed()
  {
    clearSortPos();
    int i = 0;
    for( Enumeration e = sortColumns.elements(); e.hasMoreElements(); ++i )
    {
      Object o = e.nextElement();
      int idx = userColumns.indexOf( o );
      SLColumnDefinition cd = ( SLColumnDefinition )userColumns.elementAt( idx );
      cd.setSortPos( i );
    }

    tm.setColumnList( userColumns );
    UserTblColMgr.saveColumnSet( tm );

    tm.reGenTableData();
    tm.fireTableStructureChanged();

    numLockedCols = ( int )lockedColsTF.getLong();

    dispose();
  }

  protected void clearSortPos()
  {
    for( Enumeration e = userColumns.elements(); e.hasMoreElements(); )
    {
      SLColumnDefinition cd = ( SLColumnDefinition )e.nextElement();
      cd.setSortPos( -1 );
    }
  }

  protected void cancelBtn_actionPerformed()
  {
    numLockedCols *= -1;
    dispose();
  }

  protected void toggleSortDirection( int row )
  {
    SLColumnDefinition cd = ( SLColumnDefinition )sortColumns.elementAt( row );
    cd.sortAscending = ( cd.sortAscending ? false : true );
    sortColsList.setListData( sortColumns );
    sortColsList.setSelectedIndex( row );
  }
}
